﻿// CDllMemRunDlg.cpp: 实现文件
//

#include "pch.h"
#include "HackSkill.h"
#include "CDllMemRunDlg.h"
#include "afxdialogex.h"
#include "MmLoadDll.h"

// CDllMemRunDlg 对话框

IMPLEMENT_DYNAMIC(CDllMemRunDlg, CDialogEx)

CDllMemRunDlg::CDllMemRunDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_DllMemRunDlg, pParent)
{

}

CDllMemRunDlg::~CDllMemRunDlg()
{
}

void CDllMemRunDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CDllMemRunDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON1, &CDllMemRunDlg::OnBnClickedButton1)
	ON_WM_DROPFILES()
END_MESSAGE_MAP()


// CDllMemRunDlg 消息处理程序


void CDllMemRunDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	//显示文件路径
	CWnd* pWnd = GetDlgItem(IDC_MFCEDITBROWSE1);
	csPath = L"";
	pWnd->GetWindowTextW(csPath);
	if (L"" == csPath)
	{
		MessageBox(L"没有拖拽文件！", L"提示");
		return;
	}
	
	//函数T2A和W2A均支持ATL和MFC中的字符
	USES_CONVERSION;
	char* szFileName = T2A(csPath);

	// 打开DLL文件并获取DLL文件大小
	HANDLE hFile = ::CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_ARCHIVE, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		ShowError("CreateFile");
		return;
	}
	DWORD dwFileSize = ::GetFileSize(hFile, NULL);
	// 申请动态内存并读取DLL到内存中
	BYTE* lpData = new BYTE[dwFileSize];
	if (NULL == lpData)
	{
		ShowError("new");
		return;
	}
	DWORD dwRet = 0;
	::ReadFile(hFile, lpData, dwFileSize, &dwRet, NULL);

	// 将内存DLL加载到程序中
	LPVOID lpBaseAddress = MmLoadLibrary(lpData, dwFileSize);
	if (NULL == lpBaseAddress)
	{
		ShowError("MmLoadLibrary");
		return;
	}
	MessageBox(L"DLL加载成功!", L"提示");

	// 获取DLL导出函数并调用
	typedef BOOL(*typedef_ShowMessage)(char* lpszText, char* lpszCaption);
	typedef_ShowMessage ShowMessage = (typedef_ShowMessage)MmGetProcAddress(lpBaseAddress, "ShowMessage");
	if (NULL == ShowMessage)
	{
		ShowError("MmGetProcAddress");
		return;
	}
	ShowMessage("I am DemonMan！\n", "Who Are You？");

	// 释放从内存加载的DLL
	BOOL bRet = MmFreeLibrary(lpBaseAddress);
	if (FALSE == bRet)
	{
		ShowError("MmFreeLirbary");
	}

	// 释放
	delete[] lpData;
	lpData = NULL;
	::CloseHandle(hFile);
	return;
}


void CDllMemRunDlg::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	UINT count = 0;

	csPath = _T("");

	//从成功的拖放操作中检索文件的名称，获取拖拽文件的数目
	count = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);

	//如果只拖拽一个文件夹
	if (count == 1)
	{
		//获得拖拽的文件名
		DragQueryFile(hDropInfo, 0, filePath, sizeof(filePath));

		//保存文件路径
		csPath = filePath;

		//显示文件路径
		CWnd* pWnd = GetDlgItem(IDC_MFCEDITBROWSE1);
		pWnd->SetWindowText(filePath);
	}
	else if (count > 1)
	{
		MessageBox(_T("不支持多个文件！"), _T("提示"));
	}
	CDialogEx::OnDropFiles(hDropInfo);
}


BOOL CDllMemRunDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	// 解决以管理员运行，接收不到DropFile
	ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
	ChangeWindowMessageFilter(0x0049, MSGFLT_ADD); // 0x0049 == WM_COPYGLOBALDATA
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}
